package com.acme.bankapp.domain.bank;

import com.acme.bankapp.domain.exceptions.NotEnoughFundsException;

/**
 * Created by zurdan on 14.11.14.
 * E-mail: Zurdanium@gmail.com
 */
public abstract class AbstractAccount implements Account {
    private double balance;

    public AbstractAccount(final double amount) {
        if (amount < 0) {
            throw new IllegalArgumentException("Negative start balance");
        }
        this.balance = amount;
    }

    protected void setBalance(double balance) {
        this.balance = balance;
    }

    public double getBalance() {
        return balance;
    }

    /**
     * Template method used. Implementation in {@link #doWithdraw(double)}
     * @throws NotEnoughFundsException
     */
    @Override
    public final void withdraw(final double amount) throws NotEnoughFundsException {
        if (amount < 0) {
            throw new IllegalArgumentException("Negative amount");
        }
        doWithdraw(amount);
    }

    protected abstract void doWithdraw(final double amount) throws NotEnoughFundsException;

    /**
     * Template method used. Implementation in {@link #doDeposit(double)}
     */
    @Override
    public final void deposit(final double amount) {
        if (amount < 0) {
            throw new IllegalArgumentException("Negative amount");
        }
        doDeposit(amount);
    }

    protected abstract void doDeposit(final double amount);

    protected boolean isMoneyEnough(final double amount) {
        return maximumAmountToWithdraw() >= amount;
    }

    public long decimalValue() {
        return Math.round(balance);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof AbstractAccount)) return false;

        AbstractAccount that = (AbstractAccount) o;

        if (Double.compare(that.balance, balance) != 0) return false;

        return true;
    }

    @Override
    public int hashCode() {
        long temp = Double.doubleToLongBits(balance);
        return (int) (temp ^ (temp >>> 32));
    }
}
